home *** CD-ROM | disk | FTP | other *** search
/ Qoole for Quake / Qoole for Quake (USA) / Qoole for Quake (USA).bin / Tutorial / HTML / QUBE.ZIP / SRC / OUTSIDE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-05  |  5.7 KB  |  305 lines

  1.  
  2. #include "bsp5.h"
  3.  
  4. int        outleafs;
  5.  
  6. /*
  7. ===========
  8. PointInLeaf
  9. ===========
  10. */
  11. node_t    *PointInLeaf (node_t *node, vec3_t point)
  12. {
  13.     double    d;
  14.     
  15.     if (node->contents)
  16.         return node;
  17.         
  18.     d = DotProduct (planes[node->planenum].normal, point) - planes[node->planenum]. dist;
  19.     
  20.     if (d > 0)
  21.         return PointInLeaf (node->children[0], point);
  22.     
  23.     return PointInLeaf (node->children[1], point);
  24. }
  25.  
  26. /*
  27. ===========
  28. PlaceOccupant
  29. ===========
  30. */
  31. qboolean PlaceOccupant (int num, vec3_t point, node_t *headnode)
  32. {
  33.     node_t    *n;
  34.  
  35.     if (IsPathCorner(num)) return true;
  36.         
  37.     n = PointInLeaf (headnode, point);
  38.     if (n->contents == CONTENTS_SOLID)
  39.         return false;
  40.     n->occupied = num;
  41.     return true;
  42. }
  43.  
  44.  
  45. /*
  46. ==============
  47. MarkLeakTrail
  48. ==============
  49. */
  50. portal_t    *prevleaknode;
  51. FILE    *leakfile;
  52. void MarkLeakTrail (portal_t *n2)
  53. {
  54.     int        i, j;
  55.     vec3_t    p1, p2, dir;
  56.     float    len;
  57.     portal_t *n1;
  58.  
  59.     if (hullnum)
  60.         return;
  61.  
  62.     n1 = prevleaknode;
  63.     prevleaknode = n2;
  64.     
  65.     if (!n1)
  66.         return;
  67.         
  68.     VectorCopy (n2->winding->points[0], p1);
  69.     for (i=1 ; i< n2->winding->numpoints ; i++)
  70.     {
  71.         for (j=0 ; j<3 ; j++)
  72.             p1[j] = (p1[j] + n2->winding->points[i][j]) / 2;
  73.     }
  74.     
  75.     VectorCopy (n1->winding->points[0], p2);
  76.     for (i=1 ; i< n1->winding->numpoints ; i++)
  77.     {
  78.         for (j=0 ; j<3 ; j++)
  79.             p2[j] = (p2[j] + n1->winding->points[i][j]) / 2;
  80.     }
  81.         
  82.     VectorSubtract (p2, p1, dir);
  83.     len = VectorLength (dir);
  84.     VectorNormalize (dir);
  85.     
  86.     while (len > 2)
  87.     {
  88.         fprintf (leakfile,"%f %f %f\n", p1[0], p1[1], p1[2]);
  89.         for (i=0 ; i<3 ; i++)
  90.             p1[i] += dir[i]*2;
  91.         len -= 2;
  92.     }
  93. }
  94.  
  95. void EntityHitError(int hit)
  96. {
  97.     entity_t    *ent = entities + hit;
  98.     char        classname[MAX_VALUE];
  99.     char        targetname[MAX_VALUE];
  100.     epair_t     *temp;
  101.     double        *v;
  102.  
  103.     classname[0] = targetname[0] = '\0';
  104.  
  105.     for (temp = ent->epairs; temp != NULL; temp = temp->next) {
  106.         if (strcmp(temp->key, "classname") == 0)
  107.             strcpy(classname, temp->value);
  108.         else if (strcmp(temp->key, "targetname") == 0)
  109.             strcpy(targetname, temp->value);
  110.     }
  111.  
  112.     v = ent->origin;
  113.  
  114.     ShowWarningEntry("Outside fill reached entity.");
  115.     if (targetname[0] != '\0')
  116.         ShowWarningEntry("%s:%s", classname, targetname);
  117.     else
  118.         ShowWarningEntry("%s", classname);
  119.  
  120.     ShowWarningEntry("at (%.0f,%.0f,%.0f)", v[0], v[1], v[2]);
  121.     sleep(1);
  122. }
  123.  
  124. int IsPathCorner(int hit)
  125. {
  126.     if (strcmp(ValueForKey(entities+hit, "classname"), "path_corner") == 0)
  127.         return 1;
  128.     else
  129.         return 0;
  130. }
  131.  
  132. /*
  133. ==================
  134. RecursiveFillOutside
  135.  
  136. If fill is false, just check, don't fill
  137. Returns true if an occupied leaf is reached
  138. ==================
  139. */
  140. int        hit_occupied;
  141. int        backdraw;
  142. qboolean RecursiveFillOutside (node_t *l, qboolean fill)
  143. {
  144.     portal_t    *p;
  145.     int            s;
  146.     int            original_contents;
  147.  
  148.     if (l->contents == CONTENTS_SOLID)
  149.         return false;
  150.         
  151.     if (l->valid == valid)
  152.         return false;
  153.     
  154.     l->valid = valid;
  155.  
  156. /* Some people have been intentionaly putting lights inside sky volumes, */
  157. /* so I have to fail the check now that I am testing */
  158.     if (l->occupied && l->contents != CONTENTS_SKY && !IsPathCorner(l->occupied))
  159.     {
  160.         hit_occupied = l->occupied;
  161.  
  162.         EntityHitError(hit_occupied);
  163.  
  164.                 /*drawflag = true; */
  165.         backdraw = 4000;
  166.         Draw_ClearWindow ();
  167.         DrawLeaf (l, 2);
  168.  
  169.                 return true;
  170.         }
  171.  
  172. /* fill it and it's neighbors */
  173.     original_contents = l->contents;
  174.     if (fill)
  175.         l->contents = CONTENTS_SOLID;
  176.     outleafs++;
  177.  
  178.     for (p=l->portals ; p ; )
  179.     {
  180.         s = (p->nodes[0] == l);
  181.  
  182.     /* flood fill into skys, but not back out */
  183.         if (original_contents != CONTENTS_SKY ||
  184.         p->nodes[s]->contents == CONTENTS_SKY )
  185.         {
  186.             if (RecursiveFillOutside (p->nodes[s], fill) )
  187.             {    /* leaked, so stop filling */
  188.                 if (backdraw-- > 0)
  189.                 {                
  190.                     MarkLeakTrail (p);
  191.                     DrawLeaf (l, 2);
  192.                 }
  193.                 return true;
  194.             }
  195.         }
  196.         p = p->next[!s];
  197.     }
  198.     
  199.     return false;
  200. }
  201.  
  202. /*
  203. ==================
  204. ClearOutFaces
  205.  
  206. ==================
  207. */
  208. void ClearOutFaces (node_t *node)
  209. {
  210.     face_t    **fp;
  211.     
  212.     if (node->planenum != -1)
  213.     {
  214.         ClearOutFaces (node->children[0]);
  215.         ClearOutFaces (node->children[1]);
  216.         return;
  217.     }
  218.     if (node->contents != CONTENTS_SOLID)
  219.         return;
  220.  
  221.     for (fp=node->markfaces ; *fp ; fp++)
  222.     {
  223.     /* mark all the original faces that are removed */
  224.         (*fp)->numpoints = 0;
  225.     }
  226.     node->faces = NULL;
  227. }
  228.  
  229.  
  230. /*============================================================================= */
  231.  
  232. /*
  233. ===========
  234. FillOutside
  235.  
  236. ===========
  237. */
  238. qboolean FillOutside (node_t *node)
  239. {
  240.     int            s;
  241.     int            i;
  242.     qboolean    inside;
  243.     
  244.     ShowStatusEntry("Filling in outside space.");
  245.     if (nofill)
  246.     {
  247.         ShowTempEntry("Skipped.");
  248.         return false;
  249.     }
  250.         
  251.     inside = false;
  252.     for (i=1 ; i<num_entities ; i++)
  253.     {
  254.         if (!VectorCompare(entities[i].origin, vec3_origin))
  255.         {
  256.             if (PlaceOccupant (i, entities[i].origin, node))
  257.                 inside = true;
  258.         }
  259.         }
  260.  
  261.     if (!inside)
  262.     {
  263.         ShowWarningEntry("Hullnum %i:  Entity in empty space.", hullnum);
  264.         ShowWarningEntry("No filling performed.");
  265.         sleep(1);
  266.                 return false;
  267.     }
  268.  
  269.     s = !(outside_node.portals->nodes[1] == &outside_node);
  270.  
  271. /* first check to see if an occupied leaf is hit */
  272.     outleafs = 0;
  273.     valid++;
  274.  
  275.     prevleaknode = NULL;
  276.     
  277.     if (!hullnum)
  278.     {
  279.         leakfile = fopen (pointfilename, "w");
  280.         if (!leakfile)
  281.             Error ("Couldn't open %s\n", pointfilename);
  282.     }
  283.  
  284.         if (RecursiveFillOutside (outside_node.portals->nodes[s], false))
  285.     {
  286.                 if (!hullnum)
  287.             fclose (leakfile);
  288.         return false;
  289.     }
  290.     if (!hullnum)
  291.         fclose (leakfile);
  292.  
  293. /* now go back and fill things in */
  294.     valid++;
  295.     RecursiveFillOutside (outside_node.portals->nodes[s], true);
  296.  
  297. /* remove faces from filled in leafs     */
  298.     ClearOutFaces (node);
  299.     
  300.     ShowTempEntry("%5i outside leafs filled.", outleafs);
  301.     return true;
  302. }
  303.  
  304.  
  305.